package com.cy.pj.sys.service.impl;

import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.common.annotation.RequiredTime;
import com.cy.pj.sys.dao.SysLogDao;
import com.cy.pj.sys.pojo.SysLog;
import com.cy.pj.sys.service.SysLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @Async注解描述的方法为一个异步切入点方法，这个方法执行时底层会创建新的线程
 */
@Service
/**
 * 用户日志业务层
 */
@Transactional(readOnly = false,timeout = 60,rollbackFor = Throwable.class,isolation = Isolation.READ_COMMITTED)
//timeout = -1线程阻塞了就一直等着 readOnly = false 不允许并发 timeout = 60 超出60秒抛出异常
// rollbackFor = Throwable.class 出现异常就回滚
// isolation = Isolation.READ_COMMITTED 隔离级别 为了防止数据库的脏读（Isolation.READ_COMMITTED）、幻读、不可重复读(REPEATABLE_READ)
// Isolation.SERIALIZABLE最安全 性能低 当一个人在改表时其它人只能等着（金融行业）
public class SysLogServiceImpl implements SysLogService {
    @Autowired
    private SysLogDao sysLogDao;
//    @RequiredTime
//    @RequiredLog(operation = "插入日志")//此注解描述切点

    /**
     * @Async注解描述的方法为一个异步切入点方法，这个方法执行时底层会在新的线程进行调用
     * @param syslog
     * @return
     */
    @Async
    @Override
//若是想要使用Integer 我们的异步处理 所以要使用Future n new AsyncResult<Integer>(rows
//    public Future<Integer> saveLog(SysLog sysLog) {
        public void saveLog(SysLog syslog){
//        save.log.thread->http-nio-80-exec-6
//        save.log.thread->Thread-10
//        save.log.thread->task-1
        System.out.println("save.log.thread->"+Thread.currentThread().getName());
        //模拟耗时操作
        try{Thread.sleep(10000);}catch (Exception e){}
//        try{ TimeUnit.SECONDS.sleep(10); }catch(Exception e){}
//        int rows = sysLogDao.insertLog(sysLog);
//        return new AsyncResult<Integer>(rows);
    }
    @Transactional//此注解方法执行时失败会发生回滚（单体架构使用这个可以实现回滚）
    @RequiredLog(operation = "删除日志")
    @Override
    public int deleteLog(Long... ids) {
//        for (int i = 1; i < ids.length; i++) {
//            if (i == 1) {
//                throw new RuntimeException("删除失败");
//            }
            int rows = sysLogDao.deleteLogs(ids);



        return rows;
    }

    @Transactional(readOnly = true)//允许并发
    @RequiredLog(operation = "查询日志")//此注解描述切点
    @Override
    public SysLog findbyId(Long id) {
        SysLog sysLog = sysLogDao.selectById(id);
        throw new RuntimeException("删除失败");
//        return sysLog
    }

    @RequiredTime
    @RequiredLog(operation = "查询日志")//此注解描述切点
    @Override
    public List<SysLog> findLogs(SysLog sysLog) {
//        log.find.thread->http-nio-80-exec-6 若不建立新的线程将会发生线程堵塞
//        log.find.thread->http-nio-80-exec-1 两个线程同时执行 异步处理 防止了非核心业务影响核心业务执行
//        log.find.thread->http-nio-80-exec-1 启动异步处理初始化
        System.out.println("log.find.thread->"+Thread.currentThread().getName());
        return sysLogDao.selectLogs(sysLog);
    }
}
//作业：springboot工程中AOP方式的事务控制，去查@Transactional注解的应用